package cn.chiship.framework.third.biz.wxpub.service.impl;

import cn.chiship.framework.common.service.impl.GlobalCacheServiceImpl;
import cn.chiship.framework.third.biz.wxpub.entity.*;
import cn.chiship.framework.third.biz.wxpub.mapper.ThirdWechatUserMapper;
import cn.chiship.framework.third.biz.wxpub.service.ThirdWechatAutoReplyService;
import cn.chiship.framework.third.biz.wxpub.service.ThirdWechatUserService;
import cn.chiship.framework.third.biz.wxpub.service.WeixinService;
import cn.chiship.framework.third.core.common.AutoReplyMessageTypeEnum;
import cn.chiship.framework.third.core.common.MaterialsTypeEnum;
import cn.chiship.framework.third.core.common.WechatUtils;
import cn.chiship.sdk.core.exception.ExceptionUtil;
import cn.chiship.sdk.core.exception.custom.BusinessException;
import cn.chiship.sdk.core.util.Base64Util;
import cn.chiship.sdk.core.util.ObjectUtil;
import cn.chiship.sdk.core.util.RandomUtil;
import cn.chiship.sdk.core.util.StringUtil;

import cn.chiship.sdk.third.core.common.ThirdOauthChannelEnum;
import cn.chiship.sdk.third.core.common.ThirdOauthLoginDto;
import cn.chiship.sdk.third.core.model.WeiXinConfigModel;
import cn.chiship.sdk.third.core.wx.enums.WxPubEventTypeEnum;
import cn.chiship.sdk.third.core.wx.enums.WxPubMessageTypeEnum;
import cn.chiship.sdk.third.core.wx.pub.entity.ReplyImageTextMessageItem;
import cn.chiship.sdk.third.service.WxPubService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.chiship.sdk.core.base.BaseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author lijian
 */
@Service
public class WeixinServiceImpl implements WeixinService {

    private static final Logger LOGGER = LoggerFactory.getLogger(WeixinServiceImpl.class);

    private static final String STRING_FROM_USER = "fromUserName";

    private static final String STRING_TO_USER = "toUserName";

    private static final String STRING_MSG_TYPE = "msgType";

    private static final String STRING_EVENT = "event";

    private static final String STRING_EVENT_KEY = "eventKey";

    private static final String STRING_CONTENT = "content";

    @Resource
    private ThirdWechatUserService wechatUserService;

    @Resource
    private ThirdWechatUserMapper wechatUserMapper;

    @Resource
    private WxPubService wxPubService;

    @Resource
    private ThirdWechatAutoReplyService thirdWechatAutoReplyService;

    @Resource
    private GlobalCacheServiceImpl globalCacheService;

    @Value("${chiship.third.wx-pub.h5-article-preview}")
    private String h5ArticlePreview;


    @Override
    public String analysisMessage(Map<String, String> params) {
        // 发送者
        String fromUserName = params.get(STRING_FROM_USER);
        // 接收者
        String toUserName = params.get(STRING_TO_USER);
        // 消息类型
        String msgType = params.get(STRING_MSG_TYPE);

        String appKey = params.get("appKey");

        String appSecret = params.get("appSecret");

        WeiXinConfigModel weiXinConfigModel = new WeiXinConfigModel(appKey, appSecret);
        wxPubService.config(weiXinConfigModel);
        String message = null;

        /**
         * 事件消息
         */
        if (WxPubMessageTypeEnum.WX_PUB_MESSAGE_EVENT.getType().equals(msgType)) {
            String eventType = params.get(STRING_EVENT).toLowerCase();
            String eventKey = params.get(STRING_EVENT_KEY);
            /**
             * 关注事件
             */
            if (WxPubEventTypeEnum.WX_PUB_EVENT_SUBSCRIBE.getType().equals(eventType)) {
                message = subScribe(appKey, fromUserName, toUserName);
            }
            /**
             * 取消关注事件
             */
            if (WxPubEventTypeEnum.WX_PUB_EVENT_UNSUBSCRIBE.getType().equals(eventType)) {
                unsubScribe(appKey, fromUserName);
            }
            /**
             * 菜单单击事件
             */
            if (WxPubEventTypeEnum.WX_PUB_EVENT_CLICK.getType().equals(eventType)) {
                message = sendAutoReplyMsg(appKey, fromUserName, toUserName,
                        AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_MENU, eventKey);
            }
        } else if (WxPubMessageTypeEnum.WX_PUB_MESSAGE_TEXT.getType().equals(msgType)) {
            message = sendAutoReplyMsg(appKey, fromUserName, toUserName,
                    AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_KEYWORD, null, msgType,
                    params.get(STRING_CONTENT));
        } else {
            message = sendAutoReplyMsg(appKey, fromUserName, toUserName,
                    AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_NORMAL, null, msgType, null);
        }
        if (StringUtil.isNullOrEmpty(message)) {
            message = wxPubService.replyTextMessage(fromUserName, toUserName, "小码哥正在努力接入中...");

        }
        return message;

    }

    /**
     * 首次关注
     *
     * @param fromUserName
     * @param toUserName
     * @return
     */
    public String subScribe(String appKey, String fromUserName, String toUserName) {
        wxPubService.token();
        BaseResult userResult = wxPubService.getUserInfo(fromUserName);
        if (userResult.isSuccess()) {
            JSONObject userJson = (JSONObject) userResult.getData();
            // 缓存openId
            ThirdWechatUser wechatUser = WechatUtils.convertJsonToWechatUser(userJson);
            wechatUser.setAppId(appKey);
            wechatUserService.saveWechatUser(wechatUser);

        }
        return sendAutoReplyMsg(appKey, fromUserName, toUserName, AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_SUB,
                null);
    }

    /**
     * 取消关注
     *
     * @param fromUserName
     */
    public void unsubScribe(String appKey, String fromUserName) {
        BaseResult baseResult = wechatUserService.getByAppIdAndOpenId(appKey, fromUserName);
        if (!baseResult.isSuccess()) {
            return;
        }
        ThirdWechatUser wechatUser = (ThirdWechatUser) baseResult.getData();
        wechatUser.setIsCancle(Byte.valueOf("1"));
        wechatUser.setUnSubscripeTime(System.currentTimeMillis());
        wechatUserMapper.updateByPrimaryKeySelective(wechatUser);
    }

    public String sendAutoReplyMsg(String appId, String fromUserName, String toUserName,
                                   AutoReplyMessageTypeEnum autoReplyMessageTypeEnum, String relationConfigId) {
        return sendAutoReplyMsg(appId, fromUserName, toUserName, autoReplyMessageTypeEnum, relationConfigId, null,
                null);
    }

    public String sendAutoReplyMsg(String appId, String fromUserName, String toUserName,
                                   AutoReplyMessageTypeEnum autoReplyMessageTypeEnum, String relationConfigId, String msgType,
                                   String content) {
        ThirdWechatAutoReply autoReply = null;
        if (AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_SUB.equals(autoReplyMessageTypeEnum)) {
            ThirdWechatAutoReplyExample thirdWechatAutoReplyExample = new ThirdWechatAutoReplyExample();
            thirdWechatAutoReplyExample.createCriteria().andReplayTypeEqualTo(autoReplyMessageTypeEnum.getType())
                    .andAppIdEqualTo(appId);
            List<ThirdWechatAutoReply> autoReplies = thirdWechatAutoReplyService
                    .selectByExample(thirdWechatAutoReplyExample);
            if (!autoReplies.isEmpty()) {
                autoReply = autoReplies.get(0);
            }
        } else if (AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_NORMAL.equals(autoReplyMessageTypeEnum)
                || AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_KEYWORD.equals(autoReplyMessageTypeEnum)) {
            /**
             * 消息回复规则 1.优先查询关键字 2.若无关键字，根据消息回复规则进行回复
             */
            List<ThirdWechatAutoReply> autoReplies;
            ThirdWechatAutoReplyExample thirdWechatAutoReplyExample = new ThirdWechatAutoReplyExample();
            if (!StringUtil.isNullOrEmpty(content)) {
                thirdWechatAutoReplyExample.createCriteria()
                        .andReplayTypeEqualTo(AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_KEYWORD.getType())
                        .andAppIdEqualTo(appId);
                thirdWechatAutoReplyExample.setOrderByClause("matching_type desc");
                autoReplies = thirdWechatAutoReplyService.selectByExample(thirdWechatAutoReplyExample);
                if (!autoReplies.isEmpty()) {
                    // 匹配类型 0半匹配 1全匹配
                    for (ThirdWechatAutoReply thirdWechatAutoReply : autoReplies) {
                        Byte matchType = thirdWechatAutoReply.getMatchingType();
                        String keyword = thirdWechatAutoReply.getKeyword();
                        if (Byte.valueOf("1").equals(matchType) && content.equals(keyword)) {
                            autoReply = thirdWechatAutoReply;
                            break;
                        } else if (Byte.valueOf("0").equals(matchType)
                                && (content.startsWith(keyword) || content.endsWith(keyword))) {
                            autoReply = thirdWechatAutoReply;
                            break;
                        }
                    }
                }
            }

            if (ObjectUtil.isEmpty(autoReply)) {
                thirdWechatAutoReplyExample = new ThirdWechatAutoReplyExample();
                thirdWechatAutoReplyExample.createCriteria().andAppIdEqualTo(appId)
                        .andReplayTypeEqualTo(AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_NORMAL.getType())
                        .andMessageTypeEqualTo(msgType);
                autoReplies = thirdWechatAutoReplyService.selectByExample(thirdWechatAutoReplyExample);
                if (!autoReplies.isEmpty()) {
                    if (autoReplies.size() == 1) {
                        autoReply = autoReplies.get(0);
                    } else {
                        autoReply = autoReplies.get(RandomUtil.integer(0, autoReplies.size() - 1));
                    }

                }
            }

        } else if (AutoReplyMessageTypeEnum.AUTO_REPLY_MESSAGE_TYPE_MENU.equals(autoReplyMessageTypeEnum)) {
            ThirdWechatAutoReplyExample thirdWechatAutoReplyExample = new ThirdWechatAutoReplyExample();
            thirdWechatAutoReplyExample.createCriteria().andRelationConfigIdEqualTo(relationConfigId)
                    .andAppIdEqualTo(appId);
            List<ThirdWechatAutoReply> autoReplies = thirdWechatAutoReplyService
                    .selectByExample(thirdWechatAutoReplyExample);
            if (!autoReplies.isEmpty()) {
                autoReply = autoReplies.get(0);
            }
        }
        if (ObjectUtil.isEmpty(autoReply)) {
            return wxPubService.replyTextMessage(fromUserName, toUserName, "系统不支持此类型的消息回复...");
        }
        Byte resourceType = autoReply.getResourceType();
        if (resourceType.equals(MaterialsTypeEnum.BASIC_MATERIALS_TYPE_TEXT.getType())) {
            return wxPubService.replyTextMessage(fromUserName, toUserName, autoReply.getTextContent());
        } else if (resourceType.equals(MaterialsTypeEnum.BASIC_MATERIALS_TYPE_IMAGE.getType())) {
            return wxPubService.replyImageMessage(fromUserName, toUserName, autoReply.getMediaId());
        } else if (resourceType.equals(MaterialsTypeEnum.BASIC_MATERIALS_TYPE_VOICE.getType())) {
            return wxPubService.replyVoiceMessage(fromUserName, toUserName, autoReply.getMediaId());
        } else if (resourceType.equals(MaterialsTypeEnum.BASIC_MATERIALS_TYPE_VIDEO.getType())) {
            return wxPubService.replyVideoMessage(fromUserName, toUserName, autoReply.getMediaId(),
                    autoReply.getTitle(), autoReply.getTextContent());
        } else if (resourceType.equals(MaterialsTypeEnum.BASIC_MATERIALS_TYPE_ARTICLE.getType())) {
            JSONArray articles = JSON.parseArray(autoReply.getArticleContent());
            List<ReplyImageTextMessageItem> replyImageTextMessageItems = new ArrayList<>();
            for (int i = 0; i < articles.size(); i++) {
                JSONObject article = articles.getJSONObject(i);
                ReplyImageTextMessageItem replyImageTextMessageItem = new ReplyImageTextMessageItem(
                        article.getString("title"), article.getString("textContent"),
                        // 图片路径待修改
                        article.getString("photo"),
                        // 跳转路径待修改
                        h5ArticlePreview + article.getString("articleId"));
                replyImageTextMessageItems.add(replyImageTextMessageItem);
            }

            return wxPubService.replyImageTextMessage(fromUserName, toUserName, replyImageTextMessageItems);
        }
        return wxPubService.replyTextMessage(fromUserName, toUserName, "小码哥正在努力接入中...");

    }

    @Override
    public BaseResult oauth2Auth(ThirdOauthLoginDto oauthLoginDto) {
        try {
            if (!ThirdOauthChannelEnum.OAUTH_CHANNEL_WX_PUB.equals(oauthLoginDto.getOauthChannel())) {
                return BaseResult.error("授权渠道参数错误");
            }
            wxPubService
                    .config(globalCacheService.getWeiXinConfigByAppId(oauthLoginDto.getAppId()))
                    .token();
            String callback = oauthLoginDto.getCallback();
            LOGGER.info("最终组装callback参数:{}", callback);
            callback = Base64Util.encode(callback.getBytes());
            if (callback.length() > 128) {
                return BaseResult.error("回调路径参数过长，超过128字符");
            }
            String url = wxPubService.getConnectOauth2Url(callback, false);
            LOGGER.info("url:{}", url);
            return BaseResult.ok(url);
        } catch (BusinessException businessException) {
            return businessException.formatException();
        } catch (Exception e) {
            LOGGER.error("系统错误" + e.getLocalizedMessage());
            return ExceptionUtil.formatException(e);
        }
    }
}
